/*
 * Copyright (c) 2025 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import { GestureType, FingerData, GestureMethods } from '../src/factory';

interface GestureConfig {
  __isHarmony?: boolean;
  gestureType: string; // 手势类型，如 'tap', 'pan', 'pinch' 等
  minPointers: number; // 最少手指数量，默认1
  minDistance: number; // 最小距离，默认5
  direction: string; // 方向，如 'all', 'horizontal', 'vertical' 等，默认'all'
  numberOfTaps: number; // 点击次数，默认1
  minDurationMs: number; // 最小持续时间（毫秒），默认500
  minVelocity: number; // 最小速度，默认100
  minAngle: number; // 最小角度，默认0
  repeat: boolean; // 是否重复，默认false
  onStart?: (e) => void; // 手势开始回调
  onUpdate?: (e) => void; // 手势更新回调
  onEnd?: (e) => void; // 手势结束回调
  onCancel?: (e) => void; // 手势取消回调
  onHover?: (e) => void; // 悬停回调
}

type GestureEventHandlers = Pick<GestureConfig, 'onStart' | 'onUpdate' | 'onEnd' | 'onCancel' | 'onHover'>;

function setMinPointers(config: GestureConfig, n: number, api: GestureMethods): GestureMethods {
  config.minPointers = Math.min(Math.max(1, n), 10);
  return api;
}

function setMinDistance(config: GestureConfig, n: number, api: GestureMethods): GestureMethods {
  config.minDistance = n < 0 ? 5 : n;
  return api;
}

function setDirection(config: GestureConfig, v: string, api: GestureMethods): GestureMethods {
  config.direction = isValidDirection(v) ? v : 'all';
  return api;
}

function setMinVelocity(config: GestureConfig, n: number, api: GestureMethods): GestureMethods {
  config.minVelocity = n < 0 ? 100 : n;
  return api;
}

function setNumberOfTaps(config: GestureConfig, n: number, api: GestureMethods): GestureMethods {
  config.numberOfTaps = Math.max(1, n);
  return api;
}

function setMinDuration(config: GestureConfig, n: number, api: GestureMethods): GestureMethods {
  config.minDurationMs = n < 0 ? 500 : n;
  return api;
}

function setMinAngle(config: GestureConfig, n: number, api: GestureMethods): GestureMethods {
  config.minAngle = n < 0 ? 0 : n;
  return api;
}

function setRepeat(config: GestureConfig, value: boolean, api: GestureMethods): GestureMethods {
  config.repeat = value;
  return api;
}

function setEventHandler(
  config: GestureConfig,
  eventName: keyof GestureEventHandlers,
  cb: (e) => void,
  type: GestureType,
  api: GestureMethods,
): GestureMethods {
  config[eventName] = (event): void => {
    const processedEvent = processGestureEvent(type, event);
    cb(processedEvent);
  };
  return api;
}

function createGestureAPI(config: GestureConfig, type: GestureType): GestureMethods {
  const api: GestureMethods = {
    minPointers: (n: number) => setMinPointers(config, n, api),
    minDistance: (n: number) => setMinDistance(config, n, api),
    direction: (v: string) => setDirection(config, v, api),
    minVelocity: (n: number) => setMinVelocity(config, n, api),
    numberOfTaps: (n: number) => setNumberOfTaps(config, n, api),
    minDuration: (n: number) => setMinDuration(config, n, api),
    minAngle: (n: number) => setMinAngle(config, n, api),
    repeat: (value: boolean) => setRepeat(config, value, api),
    onStart: (cb: (e) => void) => setEventHandler(config, 'onStart', cb, type, api),
    onUpdate: (cb: (e) => void) => setEventHandler(config, 'onUpdate', cb, type, api),
    onEnd: (cb: (e) => void) => setEventHandler(config, 'onEnd', cb, type, api),
    onCancel: (cb: (e) => void) => setEventHandler(config, 'onCancel', cb, type, api),
    onHover: (cb: (e) => void) => setEventHandler(config, 'onHover', cb, type, api),
    __gestureConfig: config,
  };
  return api;
}

export function createHarmonyGesture(type: GestureType): GestureMethods {
  const config: GestureConfig = {
    __isHarmony: true,
    gestureType: type,
    minPointers: 1,
    minDistance: 5,
    direction: 'all',
    numberOfTaps: 1,
    minDurationMs: 500,
    minVelocity: 100,
    minAngle: 0,
    repeat: false,
  };

  const api = createGestureAPI(config, type);
  return api;
}

function transformFingerList(fingerArray: number[][]): FingerData[] {
  if (!fingerArray || !Array.isArray(fingerArray)) {
    return [];
  }
  return fingerArray
    .map(finger => ({
      pointId: finger[0],
      x: finger[1],
      y: finger[2],
      windowX: finger[3],
      windowY: finger[4],
      displayX: finger[5],
      displayY: finger[6],
      tiltX: finger[7],
      tiltY: finger[8],
    }))
    .filter(Boolean);
}

function processGestureEvent(type: GestureType, event: any): any {
  const gestureEvent = event.nativeEvent ?? event;
  const result: any = { type };
  const fingers = transformFingerList(gestureEvent.fingerList);

  if (type !== 'pinch' && type !== 'rotation' && fingers.length > 0) {
    result.x = fingers[0].x;
    result.y = fingers[0].y;
    result.absoluteX = fingers[0].windowX;
    result.absoluteY = fingers[0].windowY;
  }
  result.fingers = fingers;
  result.timestamp = gestureEvent.timestamp || Date.now();

  // 获取对应类型的结果字段
  let resultFields: string[];
  switch (type) {
    case 'longPress':
      result.repeat = gestureEvent.repeat;
      break;
    case 'pan':
      result.velocityX = gestureEvent.velocityX;
      result.velocityY = gestureEvent.velocityY;
      result.velocity = gestureEvent.velocity;
      result.translationX = gestureEvent.offsetX;
      result.translationY = gestureEvent.offsetY;
      break;
    case 'rotation':
      result.rotation = gestureEvent.angle * (Math.PI / 180);
      break;
    case 'pinch':
      result.focalX = gestureEvent.pinchCenterX;
      result.focalY = gestureEvent.pinchCenterY;
      result.scale = gestureEvent.scale;
      break;
    case 'fling':
      result.rotation = gestureEvent.angle * (Math.PI / 180);
      result.velocity = gestureEvent.speed;
      break;
    case 'hover':
      result.isHover = gestureEvent.isHover || false;
      break;
    case 'tap':
    default:
      break;
  }

  return result;
}

function isValidDirection(directionStr: string): boolean {
  if (typeof directionStr !== 'string' || directionStr.trim() === '') {
    console.warn('Invalid direction string:', directionStr);
    return false;
  }
  const allowed = new Set(['all', 'horizontal', 'vertical', 'left', 'right', 'up', 'down', 'none']);
  // 情况1：直接匹配单个有效值
  if (allowed.has(directionStr.trim())) {
    return true;
  }
  // 情况2：检查是否包含 & 或 |
  if (!directionStr.includes('&') && !directionStr.includes('|')) {
    console.warn('Invalid direction string, must contain & or |:', directionStr);
    return false;
  }
  // 分割字符串
  const parts = directionStr.split(/[&|]/);
  // 确保分割后的部分数量 >= 2 且无空字符串
  if (parts.length < 2) {
    console.warn('Invalid direction string, must have at least two parts:', directionStr);
    return false;
  }
  for (const part of parts) {
    if (part === '' || !allowed.has(part.trim())) {
      console.warn('Invalid direction part:', part, 'in string:', directionStr);
      return false;
    }
  }
  return true;
}
